<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

class isUpTask extends baseWemTask
{
    private $ports;
    
    public function configure()
    {
        parent::configure();
        
        $this->name      = 'isUp';
        $this->briefDescription = '"ping" style function that check if a host is UP';
        
         $this->addOptions(array(
            new sfCommandOption('verbose', null,sfCommandOption::PARAMETER_NONE, 'Task Verbosity'),));
        
        //ARGUMENTS
        $this->addArgument('host',  sfCommandArgument::REQUIRED,'Remote Host to check');
        $this->addArgument('prot',  sfCommandArgument::OPTIONAL,'Protocol to use: ICMP - HTTP - FTP','ICMP');
        $this->addArgument('iter',  sfCommandArgument::OPTIONAL,'Number of iterations','4');
        
    }
    
    public function execute($arguments = array(), $options = array())
    {

        $this->addFileLogger();
        
        $this->ports=array(
        'ICMP'=>'0',
        'HTTP'=>'80',
        'FTP'=>'21');
        
        // ARGS VALIDATION
        if (key_exists($arguments['prot'],$this->ports) == FALSE){
            $this->logBlock("The provided PROTOCOL is not valid, must be ICMP or HTTP or FTP", "ERROR");
            die();
        }
                
        if ($options['verbose'])
            $this->logBlock("Sending ".$arguments['iter']." ".$arguments['prot']." packet to ".$arguments['host'].(($arguments['prot']<>"ICMP")?":".$this->ports[$arguments['prot']]:""), 'INFO');
        $method=$arguments['prot']."_Request";
        
        $isUp=false;
        $lat=array();
        for ($i=1;$i<$arguments['iter']+1;$i++){
            
            try{
                $result=$this->$method($arguments['host'],$this->ports[$arguments['prot']]);
        }catch(Exception $e){
        }
            
            $isUp=$isUp || $result['isUp'];
            //$lat=$lat+(!empty($result['latency']))?$result['latency']:0;
            if (isset($result['latency']))
                array_push($lat, $result['latency']);
            
            if ($options['verbose'])
                $this->logBlock($result['response'], 'INFO');
            
            unset($result);
        }
        
        if (count($lat)>0)
            $avLat=round(array_sum($lat)/count($lat),2);
        else
            $avLat=NULL;
        
        if ($options['verbose'])
            if ($isUp)
                    $this->logBlock('Host is UP, av. latency = '.$avLat, 'INFO');
                else
                    $this->logBlock('Host is DOWN', 'INFO');

        return array(
            "isUp" => $isUp,
            "latency" => $avLat
        );
    }
    
    /*
     * Returns an array(
     *             result,
     *             time,
     *             response);
     */
    private function ICMP_Request($host, $port, $timeout = 1) {
        
                /* ICMP ping packet with a pre-calculated checksum */
                $package =  "\x08\x00\x19\x2f\x00\x00\x00\x00\x70\x69\x6e\x67";
                $socket=socket_create(AF_INET, SOCK_RAW, 1);
                socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0));
                
                socket_connect($socket, $host, null);
                $ts = microtime(true);
                socket_send($socket, $package, strLen($package), 0);
                               
                if (socket_read($socket, 255)){
                    $lat=round((microtime(true) - $ts)*1000);
                    $result = array(
                        'isUp'=>true,
                        'latency' => $lat,
                        'response'=>"ICMP Response from ".$host." in ".$lat."ms");
                }else{
                    $result = array(
                        'isUp'=>false,
                        'response'=>"Request Timed Out");
                }
                socket_close($socket);
                 
                return $result;
        }
     
        
     private function HTTP_Request($host, $port, $timeout=5){
         
                // load the HTTP codes
                $httpCodes = parse_ini_file(sfConfig::get('sf_config_dir')."\httpCode.ini");
                    
                $url=$host.":".$port;
                $ch = curl_init($url);  
                
                //options
                curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);  
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);  
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
                $ts = microtime(true);
                $data = curl_exec($ch);  
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);  
                curl_close($ch);  
                if($httpCode>=200 && $httpCode<300){
                    $lat=round((microtime(true) - $ts)*1000);
                    $result = array(
                        'isUp'=>true,
                        'response'=>"HTTP Response from ".$host.":".$port." in ".$lat."ms, Http Info Code: ".$httpCode." [".$httpCodes[$httpCode]."]");
                }elseif ($httpCode<100){
                    
                    $result = array(
                        'isUp'=>false,
                        'response'=>"Request Timed Out");
                }else{
                    $result = array(
                        'isUp'=>false,
                        'response'=>"Http BAD Info Code: ".$httpCode." [".$httpCodes[$httpCode]."]. Try \'www\' in the front or Ping..");
                }
                return $result;
         }
         
      private function FTP_Request($host, $port, $timeout=5){  
          
                $ts = microtime(true);
                $conn_id = ftp_connect($host,$port);
                if ($conn_id){
                    $lat=round((microtime(true) - $ts)*1000);
                    $result = array(
                        'isUp'=>true,
                        'response'=>"FTP Connection with ".$host.":".$port." established in ".$lat."ms.");
                }else{
                    $result = array(
                        'isUp'=>false,
                        'response'=>"FTP Connection Failed");
                }
                ftp_close($conn_id);
                return $result;

                
      }

}

?>
